package gen.tools.deploy;

import gen.tools.Widgets;
import gen.tools.structures.DepInfo;
import gen.tools.structures.S4;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jboss.as.cli.CommandContext;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import com.google.gson.Gson;

public class DepTokyo extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public DepTokyo() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request,response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		final Widgets wid = new Widgets();
		response.setCharacterEncoding(wid.UIcodeSet);
		response.setContentType("application/text");

		ArrayList<S4> aps = null;
		final int apType = 1;	//1代表測試人員
		final DepInfo dif = new Gson().fromJson( request.getParameter("dif"), DepInfo.class);
		
		final String subsysId = dif.getSubsysId();
		final String empId = request.getParameter("empId");	//執行部署的人員
		final String squadId = "testEnvServerGroup";						//欲部署的SQUAD
		final long depId = System.currentTimeMillis();	//由於原本的手動部署中，一次部署可能包含多個動作，所以加一個depMemphisId欄位，來統一代表該次部署		
		final String fileName = dif.getFileName();					//欲部署的封裝檔名
		final long fileVer = dif.getFileVer();		//欲部署的封裝檔版次
		
		final ByteArrayOutputStream baos = new ByteArrayOutputStream();
		SVNRepository repo = null;
		InputStream inputStream = null;
		OutputStream outputStream = null;
		CommandContext cmdCtx = null;
		ModelControllerClient client = null;
		ModelNode requestNode = null;
		ModelNode result = null;
		String res = "";
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		boolean isMasterDataOK = false;	//若發生錯誤時，要留下錯誤訊息，以此判斷是要從單頭開始寫，還是單身

		
		String svnURL = "";				//SVN CM OL 封裝區 的連線位址
		String svnUSR = "";				//SVN CM OL 封裝區 的登入帳號
		String svnPWD = "";				//SVN CM OL 封裝區 的登入密碼
		
		try {
			conn = wid.getConn();
			
			//取得 AP Server的連線資訊
			aps = wid.getAP4SubsysConnInfo(subsysId, apType);
			final String apIP = aps.get(0).getS1();							//連線IP
			final int apPORT = Integer.parseInt( aps.get(0).getS2() );		//連線PORT
			final String apUSR = aps.get(0).getS3();						//登入帳號
			final char[] apPWD = aps.get(0).getS4().toCharArray();			//登入密碼
		
			//取得 SVN CM OL 封裝檔區的連線資訊
			final ArrayList<String> connInfo = wid.getSVN4SubsysConnInfo(subsysId,7);
			svnURL = connInfo.get(0);
			svnUSR = connInfo.get(1);
			svnPWD = connInfo.get(2);
			final ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(svnUSR, svnPWD);			
			
			repo = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(svnURL));
			repo.setAuthenticationManager(authManager);
			repo.getFile(fileName, fileVer, new SVNProperties(), baos);
			
			inputStream = new ByteArrayInputStream( baos.toByteArray() );
			outputStream = new FileOutputStream(new File(fileName));
	 
			int read = 0;
			byte[] bytes = new byte[1024];
	 
			while ((read = inputStream.read(bytes)) != -1) {
				outputStream.write(bytes, 0, read);
			}
			
			String strSQL = "INSERT INTO depmemphis (svnUSR,svnURL,depMemphisId,cDT,creatorId) VALUES (?,?,?,?,?)";
			ps = conn.prepareStatement(strSQL);
			ps.setString(1, svnUSR);
			ps.setString(2, svnURL);
			ps.setLong(3, depId);
			ps.setTimestamp(4, wid.cDT());
			ps.setString(5, empId);
			ps.execute();
			final int depMemphisSN = wid.getDepSN(depId);
			
			//先進行下線，再進行部署
			final String undepCommand = "undeploy " + fileName + " --all-relevant-server-groups";
			final String depCommand = "deploy " + fileName + " --server-groups=" + squadId;
			
			cmdCtx = wid.initCommandContext(apIP, apPORT, apUSR, apPWD);
			client = cmdCtx.getModelControllerClient();
			if (cmdCtx.getExitCode() == 0 && !cmdCtx.isTerminated()) {
				requestNode = cmdCtx.buildRequest(undepCommand);
				result = client.execute(requestNode);
				res = result.get("outcome").toString().substring(1, result.get("outcome").toString().length()-1);
			}
			String isSuccess = "success".equalsIgnoreCase(res)?"t":"f";
			strSQL = "INSERT INTO depmemphisdetail (depMemphisSN,depMemphisDetailId,squadId,fileName,fileVer,relativePath,isSuccess,errMsg,isAssume,isDep) VALUES (?,?,?,?,?,?,?,?,?,?)";
			//表示目前還未創建，開始創建
			ps = conn.prepareStatement(strSQL);
			ps.setInt(1, depMemphisSN);
			ps.setInt(2, wid.getLatestDepMemphisDetailId(depMemphisSN));
			ps.setString(3,squadId);
			ps.setString(4,fileName);
			ps.setLong(5,fileVer);
			ps.setString(6,fileName);
			ps.setString(7,isSuccess);
			ps.setString(8,result.toString().replaceAll("\"", "~"));
			ps.setString(9,"f");	//是否為理論值
			ps.setString(10,"f");	//是否為部署
			ps.execute();
			
			if (cmdCtx.getExitCode() == 0 && !cmdCtx.isTerminated()) {
				requestNode = cmdCtx.buildRequest(depCommand);
				result = client.execute(requestNode);
				res = result.get("outcome").toString().substring(1, result.get("outcome").toString().length()-1);
			}
			isSuccess = "success".equalsIgnoreCase(res)?"t":"f";
			//表示目前還未創建，開始創建
			ps = conn.prepareStatement(strSQL);
			ps.setInt(1, depMemphisSN);
			ps.setInt(2, wid.getLatestDepMemphisDetailId(depMemphisSN));
			ps.setString(3,squadId);
			ps.setString(4,fileName);
			ps.setLong(5,fileVer);
			ps.setString(6,fileName);
			ps.setString(7,isSuccess);
			ps.setString(8,result.toString());
			ps.setString(9,"f");	//是否為理論值
			ps.setString(10,"t");	//是否為部署
			ps.execute();
			final int toDoListId = Integer.parseInt( request.getParameter("toDoListId") );	//待辦事項的號碼
			//開始更新待辦事項
			//刪除已完成的待辦事項，將其加入待辦清單
			wid.completedList(toDoListId, empId);
						
			final String jobName = dif.isDailyBuild()?"MR":"OL"+"_"+subsysId+"_"+dif.getModId();
			final int jobSN = dif.getJobSN();
			//開始產生待測事項，即相關的需求
			strSQL = "INSERT INTO mptestresultwithreqs (modId,creatorId,cDT,jobSN,isDailyBuild,reqId) VALUES (?,?,?,?,?,?)";
			ps = conn.prepareStatement(strSQL);
			ps.setString(1, jobName);
			ps.setString(2, empId);
			ps.setTimestamp(3, wid.cDT());
			ps.setInt(4, jobSN );
			ps.setString(5, dif.isDailyBuild()?"t":"f");
			for( int i=0;i< dif.getReqs().size();i++) {
				ps.setInt(6, dif.getReqs().get(i).getI1() );
				ps.execute();
			}

			//若部署完成，則要新增等待回覆測試的待辦事項
			wid.genToDoList(subsysId, jobName+wid.TOKENONE+jobSN, empId, 4, 6);
			
			//開發主管的後門
			ps = conn.prepareStatement("SELECT MAX(toDoListId) FROM todolist");
			rs = ps.executeQuery();
			rs.next();
			strSQL="INSERT INTO todolist (subsysId,dataType,masterId,roleId,cDT,creatorId,toDoListId) VALUES (?,?,?,?,?,?,?)";
			ps = conn.prepareStatement(strSQL);
			ps.setString(1, subsysId);
			ps.setInt(2, 4);				//主檔類型，4代表測試結果的回覆
			ps.setString(3, jobName+wid.TOKENONE+jobSN);			//主檔ID
			ps.setInt(4, 4);				//角色ID, 4開發單位主管 (後門)
			ps.setTimestamp(5, wid.cDT() );
			ps.setString(6, empId );
			ps.setInt(7, rs.getInt(1) );
			ps.execute();
			
			
		} catch (Exception e) {
			wid.errLog(e);
			res = e.toString();
			int depMemphisSN=0;
			if( !isMasterDataOK ) {
				String strSQL = "INSERT INTO depmemphis (svnUSR,svnURL,depMemphisId,cDT,creatorId) VALUES (?,?,?,?,?)";
				try {
					ps = conn.prepareStatement(strSQL);
					ps.setString(1, svnUSR);
					ps.setString(2, svnURL);
					ps.setLong(3, depId);
					ps.setTimestamp(4, wid.cDT());
					ps.setString(5, empId);
					ps.execute();
					depMemphisSN = wid.getDepSN(depId);
				} catch (Exception e1) {
					wid.errLog(e1);
				}
			}
			String strSQL = "INSERT INTO depmemphisdetail (depMemphisSN,depMemphisDetailId,squadId,fileName,fileVer,relativePath,isSuccess,errMsg,isAssume,isDep) VALUES (?,?,?,?,?,?,?,?,?,?)";
			try {
				ps = conn.prepareStatement(strSQL);
				ps.setInt(1, depMemphisSN);
				ps.setInt(2, wid.getLatestDepMemphisDetailId(depMemphisSN));
				ps.setString(3,squadId);
				ps.setString(4,fileName);
				ps.setLong(5,fileVer);
				ps.setString(6,"");			
				ps.setString(7,"f");		//是否執行成功
				ps.setString(8,wid.errProcess(e));
				ps.setString(9, "f");		//是否為理論值
				ps.setString(10, "t");		//是否為部署
				ps.execute();
			} catch (Exception e1) {
				wid.errLog(e1);
			}
		} finally {
			try {
				if ( rs !=null ) {rs.close();}
				if ( ps !=null ) {ps.close();}
				if ( conn !=null ) {conn.close();}
			} catch (SQLException e) {e.printStackTrace();}
			if (repo != null) { repo.closeSession();}
			if (cmdCtx != null) {cmdCtx.terminateSession();}
			if (baos != null) {baos.close();}
			if (inputStream != null) {inputStream.close();}
			if (outputStream != null) {outputStream.close();}
		}

		response.getWriter().write(res);
	}
}
